#include "HexLineEdit.h"

#include <QKeyEvent>
#include <QTextCodec>

#include "Bridge.h"
#include "Configuration.h"
#include "ui_HexLineEdit.h"

HexLineEdit::HexLineEdit(QWidget* parent)
    : QLineEdit(parent), ui(new Ui::HexLineEdit) {
  ui->setupUi(this);

  // setup data
  mData = QByteArray();
  mKeepSize = false;
  mOverwriteMode = false;
  mEncoding = QTextCodec::codecForName("System");
  if (!mEncoding) {
    mEncoding = QTextCodec::codecForName("UTF-8");
  }

  // setup text fields
  QFont font("Monospace", 8, QFont::Normal, false);
  font.setFixedPitch(true);
  font.setStyleHint(QFont::Monospace);
  setFont(font);

  connect(this, SIGNAL(textEdited(const QString&)), this,
          SLOT(updateData(const QString&)));
}

HexLineEdit::~HexLineEdit() { delete ui; }

void HexLineEdit::keyPressEvent(QKeyEvent* event) {
  // Switch between insert/overwrite mode
  if (event->key() == Qt::Key_Insert &&
      (event->modifiers() == Qt::NoModifier)) {
    mOverwriteMode = !mOverwriteMode;
    event->ignore();
    return;
  }

  if (mOverwriteMode) {
    QString newText = event->text();
    if (!newText.isEmpty() && newText.at(0).isPrint()) {
      for (int i = 0; i < newText.size(); i++) del();
      QTextCodec::ConverterState converter(QTextCodec::IgnoreHeader);
      insert(mEncoding->fromUnicode(newText.constData(), newText.size(),
                                    &converter));
      event->ignore();
      return;
    }
  }

  QLineEdit::keyPressEvent(event);
}

void HexLineEdit::setData(const QByteArray& data) {
  QString text;
  text = mEncoding->toUnicode(data);

  mData = data;
  setText(text);
}

QByteArray HexLineEdit::data() { return mData; }

/**
 * @brief HexLineEdit::setEncoding Set the encoding of the line edit.
 * @param encoding The codec for the line edit.
 * @remarks the parameter passed in will be managed by the widget. You must use
 * a new codec.
 */
void HexLineEdit::setEncoding(QTextCodec* encoding) {
  if (encoding) {
    mEncoding = encoding;
  }
}

/**
 * @brief HexLineEdit::encoding Get the encoding of the line edit.
 * @return the codec instance of the line edit.
 */
QTextCodec* HexLineEdit::encoding() { return mEncoding; }

void HexLineEdit::setKeepSize(const bool enabled) {
  mKeepSize = enabled;
  if (enabled) {
    int dataSize = mData.size();
    int charSize;
    QTextCodec::ConverterState converter(QTextCodec::IgnoreHeader);
    charSize = mEncoding->fromUnicode(QString("A").constData(), 1, &converter)
                   .size();  // "A\0"

    setMaxLength((dataSize / charSize) + (dataSize % charSize));
  } else {
    setMaxLength(32767);
  }
}

bool HexLineEdit::keepSize() { return mKeepSize; }

void HexLineEdit::setOverwriteMode(bool overwriteMode) {
  mOverwriteMode = overwriteMode;
}

bool HexLineEdit::overwriteMode() { return mOverwriteMode; }

void HexLineEdit::updateData(const QString& arg1) {
  Q_UNUSED(arg1);

  mData = toEncodedData(text());
  emit dataEdited();
}

QByteArray HexLineEdit::toEncodedData(const QString& text) {
  QTextCodec::ConverterState converter(QTextCodec::IgnoreHeader);
  return mEncoding->fromUnicode(text.constData(), text.size(), &converter);
}
